//比较简单的英语就不翻译了
// Define a function.
testInteger(int aNumber) {
  print('The number is $aNumber.'); // Print to console.
}

//测试字符串
testString() {
  //字符串的写法有以下三种,当然也可以嵌套
  var s1 = 'ssss1';
  var s2 = "sssss2";
//三个 ' 或 " 来定义多行的String 类型
  var s3 = '''
ssss
3333
2222
''';
  print(s3);

//字符串内嵌入变量 嵌入表达式 $variableName (or ${expression})
  var s4 = "s4---$s1"; //s4---ssss1
  print(s4);

//拼接字符串
  var s5 = "dd" + "ff" + "ee";

  print("s5:$s5");

//上面的方法等价于
  var s6 = 'dd' + 'ff' + "ee";
  print("s6:$s6");

//可以通过加前缀r的方式，创建一个"raw"(原始)的字符串
//说白了 就是让字符串内的任何表达式、语法失效，原样输出
  var s7 = r"In a raw string, even \n isn't special.${3+3}";
//In a raw string, even \n isn't special.${3+3}

  print("s7:$s7");

  String s8 = '''ewrwerAeawrwer\neee''';
  String s9 = r'''ewrwerAeawrwer\neee''';
  print('========' + s8);
  print('========' + s9);

  StringBuffer sb1 = StringBuffer();
  StringBuffer sb2 = StringBuffer();
  sb1.write("333");
  sb1.write("aaa");
  sb1.write("666");
  sb2
    ..write("333")
    ..write("aaa")
    ..writeAll(['6', '6', '6']); //..级联符，可链式调用里面方法
  print(sb1); //333aaa666
  print(sb2); //333aaa666

  String a;
  print(a?.length);
  String copy = 'a';
  print('copy:${copy * 0}');
}

//测试数组
testArray() {
//  var list = [1, 2, 3]; //分析器自动推断list为List<int>,所以里面不能加入其他类型的元素
//  print(list.length); //3
//  list[1] = 11;
//  print(list.toString()); //[1, 11, 3]
//  var constantList = const [1, 2, 3];
//  // constantList[1] = 1; //因为前面的赋值使用了const 所以这句会报错.
//  constantList = [5]; //这样可以
//  print("constantList:$constantList");

  //声明
  //自动长度
  List growableList = List();
// List growableList = new List()..length = 3;
  growableList..add(1)..add(2)..add('damon');
  print('growableList: ${growableList[0]}');
  //固定长度
  var list = List(3); //List的声明，可以用var也可用List。
  list[0] = 1; //下标索引从0开始
  list[1] = 2;
  list[2] = 'damon';
  print('list: ${list}');
  //元素类型固定
  var typeList = List<int>();
  typeList.add(1);
  typeList.add(2);
  typeList.add(3);
  print('typeList: ${typeList}');
  //常用属性
  int first = typeList.first;
  print('typeList.first: ${first}'); //第一个元素
  int last = typeList.last;
  print('typeList.last: ${last}'); //最后一个元素
  int length = typeList.length;
  print('typeList.length: ${length}'); //元素个数
  bool isEmpty = typeList.isEmpty;
  print('typeList.isEmpty: ${isEmpty}'); //是否为空
  bool isNotEmpty = typeList.isNotEmpty;
  print('typeList.isNotEmpty: ${isNotEmpty}'); //是否不为空
  Iterable reversed = typeList.reversed;
  print('typeList.reversed: ${reversed}'); //倒序
  //常用方法 增删改查，排序，洗牌，复制子列表
  var list4 = [];
  //增
  list4.add(1);
  print('add 1 :${list4}');
  list4.addAll([2, 3, 4]);
  print('addAll [2, 3, 4] :${list4}');
  list4.insert(0, 0);
  print('insert(0, 0) :${list4}');
  list4.insertAll(1, [5, 6, 7]);
  print('insertAll(1, [5, 6, 7]) :${list4}');
  //删
  list4.remove(5);
  print('remove 5 :${list4}');
  list4.removeAt(2);
  print('remove at 0 :${list4}');
  //改
  list4[4] = 5;
  print('update list4[4] to 5 :$list4}');
  //range
  list4.fillRange(0, 3, 9);
  print('fillRange update list4[0]-list4[2] to 9 :$list4}');
  Iterable getRange = list4.getRange(0, 3);
  print('getRange list4[0]-list4[2] :$getRange}');
  //查
  var contains = list4.contains(5);
  print('list4 contains 5 :${contains}');
  var indexOf = list4.indexOf(1);
  print('list4 indexOf 1 :${indexOf}');
  int indexWhere = list4.indexWhere((test) => test == 5);
  print('list4 indexWhere 5 :${indexWhere}');
  //排序
  list4.sort();
  print('list4 sort :${list4}');
  //洗牌
  list4.shuffle();
  print('list4 shuffle :${list4}');
  //复制子列表
  var list5 = list4.sublist(1);
  print('sublist(1) list5 :${list5}');
  //操作符
  var list6 = [8, 9];
  print('list6 :${list6}');
  var list7 = list5 + list6;
  print('list5 + list6 :${list7}');
}

//测试循环
testFor() {
  for (var i = 0; i < 10; i++) {
    print("index ${i}");
  }

// 列表访问
  var listVar = ["china", "usa"];
//  for (var country in listVar) {
//    print(country);
//  }

  for (var i = 0; i < listVar.length; i++) {
    print("value:" + listVar[i]);
  }
}

//集合Map联合测试 https://www.jianshu.com/p/1c7d828b1153
testMapList() {
  List<Map> students = [
    {'name': 'tom', 'age': 16},
    {'name': 'jack', 'age': 18},
    {'name': 'lucy', 'age': 20},
    {'name': 'davy', 'age': 100, 'sex': '1'}
  ];
  //print(students);

  List numbers = [2, 8, 5, 1, 7, 3];

  students.forEach((student) => {print(student)});

  Map tom = {'name': 'tom', 'age': 16};
  tom.forEach((key, value) => print(key + ' : ' + value.toString()));

  var messages = students.map((student) => 'Hello ' + student['name']).toList();
  print(messages);

  print(students.contains({'name': 'tom', 'age': 16}));

  numbers.sort((num1, num2) => num1 - num2);
  print(numbers);

  List arr = [1, 3, 5, 2, 7, 9];

  print(arr.take(3).toList());
// [1, 3, 5]
  print(arr.skip(4).toList());
// [7, 9]
  print(arr.take(3).skip(2).take(1).toList());

  List arr1 = [1, 3, 5, 2, 7, 9];

  var clonedArr = List.from(arr1);
  print(clonedArr);
// [1, 3, 5, 2, 7, 9]

  var clonedArrWithMap = List.from(students);
  print(clonedArrWithMap);
  // [{name: tom, age: 16}, {name: jack, age: 18}, {name: lucy, age: 20}, {name: davy, age: 100, sex: 1}]

  List arr2 = [1, 3, 5, 9, 2, 1];

  arr2.add(10);
  print(arr2);
// [1, 3, 5, 9, 2, 1, 10]
  arr2.addAll([15, 21]);
  print(arr2);
// [1, 3, 5, 9, 2, 1, 10, 15, 21]
//转map
  print(arr2.asMap());
}

//布尔值
testBool() {
  bool bo = true;
  print(bo); //输出：null
  if (bo) {
    //报错，因为bool未初始化默认值是null，所以这样调用运行时会报错
  }
}

testTypeAS() {
//as 类型转换
  num iNum = 1;
  num dNum = 1.0;
  int i = iNum as int;
  double d = dNum as double;
//  int c = dNum as int;
  print([
    i,
    d,
  ]);

//  String s = iNum as String; //不能转换，报错

//is 如果对象是指定的类型返回 True
  print(iNum is int);

//  Child child;
//  Child child1 = new Child();
//  print(child is Parent); //child is Null
//  print(child1 is Parent);

//is! 如果对象是指定的类型返回 False
  print(iNum is! int);
  print('======');
  bool isFinish = true;
  String txtVal = isFinish ? 'yes' : 'no';
  print(txtVal);
  // expr1 ?? expr2，如果 expr1 是 non-null，返回其值； 否则执行 expr2 并返回其结果。
  bool isPaused;
  isPaused = isPaused ?? false;
  print(isPaused);
  //或者
  isPaused ??= false;
  print(isPaused);
}

//闭包
testBlock() {
  Function makeAddFun(int a) {
    a++;
    return (int b) => a + b;
  }

  // print(makeAddFun(1)(2));//相当于：
  var f = makeAddFun(1);
  print(f(2));
}

testFunc() {
  MyFunc myFunc = subtsract(2, 1);
  myFunc = add(2, 2);
  myFunc = divide(4, 2);
  // calculator(2, 1, subtsract);
}

typedef MyFunc(int a, int b);
//根据MyFunc相同的函数签名定义两个函数
add(int a, int b) {
  print('add:${a + b}');
}

subtsract(int a, int b) {
  print('subtsract: ${a - b}');
}

divide(int a, int b) {
  print('divide: ${a / b}');
}

//类定义和使用
testClassDefine() {
// 使用构造函数创建对象
  var cat = Animal("cat");
  // 也可以用new来创建对象，new从Dart2开始是可选的
  var dog = new Animal("dog");
  cat.run();
  dog.run();

  // cat不是null时，name赋予新值
  cat?.name = "small cat";
  cat.run(); // small cat is running;
  Animal nullAnimal;
  // nullAnimal是null,如果直接使用nullAnimall.name,会对象为空的报错
  nullAnimal?.name = "null";

  var rect = Rectangle(3, 4, 20, 15);
  print(rect.left == 3);
  rect.right = 12;
  print(rect.left == -8);


  print('=========');
  var bird = Bird.createInstance({
    "name": "bird"
  });
  print(bird.name); // bird
  print(bird.desc); // blue bird
}

class Animal {
  String name;

  // 构造函数
  Animal(String name) {
    this.name = name;
  }

  run() {
    print("${this.name} is running");
  }
}

// 官网实例代码
class Rectangle {

//  var rect = Rectangle(3, 4, 20, 15);
//  print(rect.left == 3);
//  rect.right = 12;
//  print(rect.left == -8);

  //
  num left = 10;
  num _left_width = 12; // 私有变量

  // 定义多个变量
  num top, width, height;
//3 /4 /20 /15
  Rectangle(this.left, this.top, this.width, this.height);

  // 定义两个计算属性: right and bottom.
  // 需要注意的是,get和set需要成对出现
  // 重写get
  num get right => left + width; //23

  // 重写set
  set right(num value) => left = value - width;//

  num get bottom => top + height;

  set bottom(num value) => top = value - height;
}

//dart2教程
//https://blog.csdn.net/qq_30938445/article/details/88931145#11__12
//https://blog.csdn.net/shanyuu/article/details/83002504
//这里是主函数 This is where the app starts executing.
main() {
  var number = 42; // Declare and initialize a variable.
  //testInteger(number); // Call a function.
  //testString();
  //testArray();
  //testFor();
  //testMapList();
  //testBool();
  //testTypeAS();
  //testBlock();
  // testFunc();
  testClassDefine();
}


class SuperAnimal{

  String name;

  String color = "yellow";

  SuperAnimal.createInstance(Map values){
    print("in animal");
    name = values["name"];
  }

  run(){
    print("${this.name} is running");
  }
}

// extends 继承的关键字
class Bird extends SuperAnimal{
  String name = "blue bird";
  String desc;

  Bird.createInstance(Map values):
        desc = values['name'], // 初始化列表，注意这里没有this
        super.createInstance(values){ // 父类方法调用使用super
    print("in bird");
  }

}



